﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using Softelligent.Zintra.Synchronizations.ContactsExpressConsole.Entities;

namespace Softelligent.Zintra.Synchronizations.ContactsExpressConsole
{
    public class ContactRepository
    {
        public ContactRepository()
        {
            Database.SetInitializer<ContactsCatalog>(null);
        }

        public Contact Fetch(string id)
        {
            var contactId = 0;
            if (!int.TryParse(id, out contactId))
            {
                return null;
            }
            using (var db = new ContactsCatalog())
            {
                return db.Contacts.Include(c => c.Address).FirstOrDefault(c => c.Id == contactId);
            }
        }

        public Batch FetchAll(int batchSize, int batchNumber)
        {
            var startBatch = (batchNumber - 1) * batchSize;
            using (var db = new ContactsCatalog())
            {
                var batchCount = Math.Ceiling((double)db.Contacts.Count() / batchSize);
                var contacts = db.Contacts.Include(c => c.Address)
                    .Select(c => c)
                    .OrderBy(si => si.Id)
                    .Skip(startBatch)
                    .Take(batchSize)
                    .ToList();
                return new Batch
                           {
                               Items = contacts,
                               Count = (int)batchCount,
                               Number = batchNumber
                           };
            }
        }

        public IEnumerable<string> FetchNotExisting(IEnumerable<string> ids)
        {
            var idsToCheck = new List<int>();
            foreach (var i in ids)
            {
                var id = 0;
                if (int.TryParse(i, out id))
                {
                    idsToCheck.Add(id);
                }
            }
            using (var db = new ContactsCatalog())
            {
                var existingIds = db.Contacts
                    .Where(c => idsToCheck.Contains(c.Id))
                    .Select(c => c.Id)
                    .ToList();
                var notExistingIds = idsToCheck.Where(i => !existingIds.Contains(i));
                return notExistingIds.Select(i => i.ToString());
            }
        }

        public Contact Save(Contact entity)
        {
            Contact contact;
            using (var db = new ContactsCatalog())
            {
                contact = db.Contacts.Include(c => c.Address).FirstOrDefault(c => c.Id == entity.Id);
                if (contact == null)
                {
                    contact = entity;
                    db.Contacts.Add(contact);
                }
                else
                {
                    contact.UnformattedName = entity.UnformattedName;
                    contact.FirstName = entity.FirstName;
                    contact.LastName = entity.LastName;
                    contact.WorkEmailAddress = entity.WorkEmailAddress;
                    contact.HomeEmailAddress = entity.HomeEmailAddress;
                    if (entity.Address == null)
                    {
                        contact.Address = null;
                    }
                    else if (contact.Address != null)
                    {
                        contact.Address.Street = entity.Address.Street;
                        contact.Address.City = entity.Address.City;
                        contact.Address.PostalCode = entity.Address.PostalCode;
                        contact.Address.State = entity.Address.State;
                        contact.Address.Country = entity.Address.Country;
                    }
                    else
                    {
                        contact.Address = entity.Address;
                    }
                }
                db.SaveChanges();
            }

            return contact;
        }

        public void Delete(string id)
        {
            var contactId = 0;
            if (!int.TryParse(id, out contactId))
            {
                return;
            }
            using (var db = new ContactsCatalog())
            {
                var contact = db.Contacts.Find(contactId);
                if (contact != null)
                {
                    db.Contacts.Remove(contact);
                    db.SaveChanges();
                }
            }
        }
    }
}
